home *** CD-ROM | disk | FTP | other *** search
/ Amiga Format CD 7 / Amiga Format AFCD07 (Dec 1996, Issue 91).iso / serious / shareware / programming / aros / dos / loadseg_elf.c < prev    next >
C/C++ Source or Header  |  1996-09-13  |  7KB  |  303 lines

  1. /*
  2.     (C) 1995-96 AROS - The Amiga Replacement OS
  3.     $Id: loadseg_elf.c,v 1.7 1996/09/13 17:50:07 digulla Exp $
  4.     $Log: loadseg_elf.c,v $
  5.     Revision 1.7  1996/09/13 17:50:07  digulla
  6.     Use IPTR
  7.  
  8.     Revision 1.6  1996/08/15 13:18:21  digulla
  9.     First attempt to allow debugging in shared code but the strings are not
  10.     loaded correctly yet
  11.  
  12.     Revision 1.5  1996/08/13 13:52:48  digulla
  13.     Replaced <dos/dosextens.h> by "dos_intern.h" or added "dos_intern.h"
  14.     Replaced __AROS_LA by __AROS_LHA
  15.  
  16.     Revision 1.4  1996/08/03 18:21:10  digulla
  17.     Added support for linked files !
  18.  
  19.     Revision 1.3  1996/08/01 17:40:54  digulla
  20.     Added standard header for all files
  21.  
  22.     Desc:
  23.     Lang:
  24. */
  25. #include <exec/memory.h>
  26. #include <clib/exec_protos.h>
  27. #include <dos/dosasl.h>
  28. #include <clib/dos_protos.h>
  29. #include <clib/aros_protos.h>
  30. #include "dos_intern.h"
  31.  
  32. extern struct DosLibrary * DOSBase;
  33.  
  34. #define SHT_PROGBITS    1
  35. #define SHT_SYMTAB    2
  36. #define SHT_STRTAB    3
  37. #define SHT_NOBITS    8
  38. #define SHT_REL     9
  39.  
  40. #define RELO_32     1
  41. #define RELO_PC32    2
  42.  
  43. struct elfheader
  44. {
  45.     UBYTE ident[16];
  46.     UWORD type;
  47.     UWORD machine;
  48.     ULONG version;
  49.     APTR entry;
  50.     ULONG phoff;
  51.     ULONG shoff;
  52.     ULONG flags;
  53.     UWORD ehsize;
  54.     UWORD phentsize;
  55.     UWORD phnum;
  56.     UWORD shentsize;
  57.     UWORD shnum;
  58.     UWORD shstrndx;
  59. };
  60.  
  61. struct sheader
  62. {
  63.     ULONG name;
  64.     ULONG type;
  65.     ULONG flags;
  66.     APTR addr;
  67.     ULONG offset;
  68.     ULONG size;
  69.     ULONG link;
  70.     ULONG info;
  71.     ULONG addralign;
  72.     ULONG entsize;
  73. };
  74.  
  75. struct symbol
  76. {
  77.     ULONG name;
  78.     ULONG value;
  79.     ULONG size;
  80.     UBYTE info;
  81.     UBYTE other;
  82.     WORD shindex;
  83. };
  84.  
  85. struct relo
  86. {
  87.     ULONG addr;
  88.     ULONG info;
  89. };
  90.  
  91. struct hunk
  92. {
  93.     ULONG size;
  94.     UBYTE *memory;
  95. };
  96.  
  97. int read_block(BPTR file, ULONG offset, APTR buffer, ULONG size)
  98. {
  99.     LONG subsize;
  100.     UBYTE *buf=(UBYTE *)buffer;
  101.     if(Seek(file,offset,OFFSET_BEGINNING)<0)
  102.     return 1;
  103.     while(size)
  104.     {
  105.     subsize=Read(file,buf,size);
  106.     if(subsize==0)
  107.     {
  108.         ((struct Process *)FindTask(NULL))->pr_Result2=ERROR_BAD_HUNK;
  109.         return 1;
  110.     }
  111.     if(subsize<0)
  112.         return 1;
  113.     buf+=subsize;
  114.     size-=subsize;
  115.     }
  116.     return 0;
  117. }
  118.  
  119. BPTR LoadSeg_ELF(BPTR file)
  120. {
  121.     UBYTE *shtab=NULL;
  122.     UBYTE *strtab=NULL;
  123.     struct symbol *symtab=NULL;
  124.     struct hunk *hunks=NULL;
  125.     struct relo *reltab=NULL;
  126.  
  127.     ULONG numsym, numrel, i;
  128.     WORD t, mint=0, maxt=0;
  129.     struct elfheader eh;
  130.     struct sheader *sh;
  131.     UBYTE *loaded;
  132.     struct symbol *symbol;
  133.     BPTR last=0;
  134.  
  135. #define ERROR(a)    { *error=a; goto end; }
  136.     LONG *error=&((struct Process *)FindTask(NULL))->pr_Result2;
  137.  
  138.     if(read_block(file,0,&eh,sizeof(eh)))
  139.     goto end;
  140.  
  141.     if(eh.ident[0]!=0x7f||eh.ident[1]!='E'||eh.ident[2]!='L'||eh.ident[3]!='F')
  142.     ERROR(ERROR_NOT_EXECUTABLE);
  143.  
  144.     if(eh.type!=1||eh.machine!=3)
  145.     ERROR(ERROR_OBJECT_WRONG_TYPE);
  146.  
  147.     shtab=(UBYTE *)AllocVec(eh.shentsize*eh.shnum,MEMF_ANY);
  148.  
  149.     if(shtab==NULL)
  150.     ERROR(ERROR_NO_FREE_STORE);
  151.  
  152.     if(read_block(file,eh.shoff,shtab,eh.shentsize*eh.shnum))
  153.     goto end;
  154.  
  155.     for(t=0;;t++)
  156.     {
  157.     if(t==eh.shnum)
  158.         ERROR(ERROR_OBJECT_WRONG_TYPE);
  159.  
  160.     sh=(struct sheader *)(shtab+t*eh.shentsize);
  161.  
  162.     if(sh->type==SHT_SYMTAB)
  163.         break;
  164.     }
  165.  
  166.     symtab=(struct symbol *)AllocVec(sh->size,MEMF_ANY);
  167.  
  168.     if(symtab==NULL)
  169.     ERROR(ERROR_NO_FREE_STORE);
  170.  
  171.     if(read_block(file,sh->offset,symtab,sh->size))
  172.     goto end;
  173.  
  174.     numsym=sh->size/sizeof(struct symbol);
  175.     mint=maxt=symtab[0].shindex;
  176.     for(i=1;i<numsym;i++)
  177.     {
  178.     if(symtab[i].shindex<mint)
  179.         mint=symtab[i].shindex;
  180.     if(symtab[i].shindex>maxt)
  181.         maxt=symtab[i].shindex;
  182.     }
  183.     hunks=(struct hunk *)AllocVec(sizeof(struct hunk)*((LONG)maxt-mint+1),MEMF_CLEAR);
  184.     if(hunks==NULL)
  185.     ERROR(ERROR_NO_FREE_STORE);
  186.     hunks-=mint;
  187.     for(t=0;t<eh.shnum;t++)
  188.     {
  189.     sh=(struct sheader *)(shtab+t*eh.shentsize);
  190.     if(sh->type==SHT_PROGBITS||sh->type==SHT_NOBITS)
  191.         hunks[t].size=sh->size;
  192.     }
  193.  
  194. #if 0 /* doesn't work :( */
  195.     if (eh.shstrndx)
  196.     {
  197.     sh = (struct sheader *)(shtab + eh.shstrndx*eh.shentsize);
  198.  
  199. kprintf ("StrTab-Section: name=%d type=%d flags=%d\n",
  200.     sh->name, sh->type,sh->flags);
  201.  
  202.     strtab=AllocVec(sh->size,MEMF_ANY);
  203.     if(symtab==NULL)
  204.         ERROR(ERROR_NO_FREE_STORE);
  205.     kprintf ("Reading StrTab at %d (offset=%ld, size=%ld)\n", eh.shstrndx, sh->offset, sh->size);
  206.     if(read_block(file,sh->offset,strtab,sh->size))
  207.         goto end;
  208.     }
  209. #endif
  210.  
  211.     for(i=0;i<numsym;i++)
  212.     if(symtab[i].shindex<0)
  213.     {
  214.         symtab[i].value=hunks[symtab[i].shindex].size;
  215.         hunks[symtab[i].shindex].size+=symtab[i].size;
  216.  
  217.         if (strtab && symtab[i].name)
  218.         kprintf ("sym %s: %ld\n", &strtab[symtab[i].name], symtab[i].value);
  219.     }
  220.     for(t=mint;t<=maxt;t++)
  221.     if(hunks[t].size)
  222.     {
  223.         hunks[t].memory=(UBYTE *)AllocVec(hunks[t].size+sizeof(BPTR),MEMF_CLEAR);
  224.         if(hunks[t].memory==NULL)
  225.         ERROR(ERROR_NO_FREE_STORE);
  226.         hunks[t].memory+=sizeof(BPTR);
  227.     }
  228.     loaded=NULL;
  229.     for(t=0;t<eh.shnum;t++)
  230.     {
  231.     sh=(struct sheader *)(shtab+t*eh.shentsize);
  232.     switch(sh->type)
  233.     {
  234.     case SHT_PROGBITS:
  235.         if(read_block(file,sh->offset,hunks[t].memory,sh->size))
  236.         goto end;
  237.         loaded=hunks[t].memory;
  238.         /* VPrintf ("Loaded PROGBITS at %08lx\n", (ULONG*)&loaded); */
  239.         break;
  240.     case SHT_REL:
  241.         if(loaded==NULL)
  242.         ERROR(ERROR_OBJECT_WRONG_TYPE);
  243.         reltab=AllocVec(sh->size,MEMF_ANY);
  244.         if(reltab==NULL)
  245.         ERROR(ERROR_NO_FREE_STORE);
  246.         if(read_block(file,sh->offset,reltab,sh->size))
  247.         goto end;
  248.         numrel=sh->size/sizeof(struct relo);
  249.         for(i=0;i<numrel;i++)
  250.         {
  251.         symbol=&symtab[reltab[i].info>>8];
  252.         switch(reltab[i].info&0xff)
  253.         {
  254.         case RELO_32:
  255.             *(ULONG *)&loaded[reltab[i].addr]+=
  256.             (IPTR)hunks[symbol->shindex].memory+symbol->value;
  257.             break;
  258.         case RELO_PC32:
  259.             *(ULONG *)&loaded[reltab[i].addr]+=
  260.             (IPTR)hunks[symbol->shindex].memory +
  261.             symbol->value - (IPTR)&loaded[reltab[i].addr];
  262.             break;
  263.         default:
  264.             ERROR(ERROR_BAD_HUNK);
  265.         }
  266.         }
  267.         FreeVec(reltab);
  268.         reltab=NULL;
  269.         loaded=NULL;
  270.         break;
  271.     }
  272.     }
  273.     for(t=mint;t<0;t++)
  274.     if(hunks[t].size)
  275.     {
  276.         ((BPTR *)hunks[t].memory)[-1]=last;
  277.         last=MKBADDR((BPTR *)hunks[t].memory-1);
  278.     }
  279.     for(t=maxt;t>=0;t--)
  280.     if(hunks[t].size)
  281.     {
  282.         ((BPTR *)hunks[t].memory)[-1]=last;
  283.         last=MKBADDR((BPTR *)hunks[t].memory-1);
  284.     }
  285.     FreeVec(hunks+mint);
  286.     hunks=NULL;
  287.  
  288. end:
  289.     FreeVec(reltab);
  290.     if(hunks!=NULL)
  291.     {
  292.     for(t=mint;t<=maxt;t++)
  293.         if(hunks[t].memory!=NULL)
  294.         FreeVec(hunks[t].memory-sizeof(BPTR));
  295.     FreeVec(hunks+mint);
  296.     }
  297.     if (strtab)
  298.     FreeVec (strtab);
  299.     FreeVec(symtab);
  300.     FreeVec(shtab);
  301.     return last;
  302. }
  303.